package com.qqbot.listener;

import com.alibaba.fastjson.JSONObject;
import com.qqbot.annotation.GroupAnnotation;
import com.qqbot.enums.IdentityEnum;
import com.qqbot.enums.WolfKillStatusEnum;
import com.qqbot.exception.BusinessException;
import com.qqbot.model.wolfkill.Identity;
import com.qqbot.model.wolfkill.Vote;
import com.qqbot.utils.*;
import lombok.extern.slf4j.Slf4j;
import love.forte.simboot.annotation.Filter;
import love.forte.simboot.annotation.FilterValue;
import love.forte.simboot.annotation.Listener;
import love.forte.simbot.application.Application;
import love.forte.simbot.application.BotManagers;
import love.forte.simbot.bot.Bot;
import love.forte.simbot.definition.Group;
import love.forte.simbot.definition.GroupMember;
import love.forte.simbot.event.EventResult;
import love.forte.simbot.event.FriendMessageEvent;
import love.forte.simbot.event.GroupMessageEvent;
import org.apache.commons.lang3.StringUtils;
import org.redisson.api.RBlockingQueue;
import org.redisson.api.RDelayedQueue;
import org.redisson.api.RLock;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @author 付亚全
 */
@Component
@Slf4j
public class WolfKillListener {

    //天黑刀人状态、天黑预言状态、天黑女巫毒药-解药、死者留遗言状态、轮流发言状态、投票状态
    private static Map<String, Identity> map = new HashMap();

    private static boolean wolfKillStatus = false;

    private static List<String> identityList = Arrays.asList("村民", "村民", "村民", "村民", "狼人", "狼人", "狼人", "预言家", "女巫", "猎人");

    @Autowired
    private RedissonUtil redissonUtil;

    @Autowired
    private Application application;

    @Listener
    @GroupAnnotation(value = true)
    @Filter(value = "开启狼人杀")
    public EventResult startWolfKill(GroupMessageEvent event) {
        log.info("WolfKillListener.startWolfKill.params=====>sender:{}", event.getAuthor().getId());
        if (!startWolfKill()) {
            return EventResult.truncate();
        }
        map.put("702272198", null);
        map.put("3503651428", null);
        map.put("1154220981", null);
        map.put("2661723102", null);
        map.put("2422248615", null);
        map.put("3092515903", null);
        map.put("1715182483", null);
        map.put("2632238487", null);
        map.put("329249172", null);
        map.put("2644502646", null);
        event.getGroup().sendBlocking("狼人杀已开启，发送“报名”加入队伍，当前报名人数：" + identityList.size() + "/" + map.size());
        return EventResult.truncate();
    }

    @Listener
    @Filter(value = "报名")
    public EventResult signUp(GroupMessageEvent event) throws InterruptedException, BusinessException {
        if (!wolfKillStatus) {
            return EventResult.truncate();
        }
        String qq = event.getAuthor().getId().toString();
        Group group = event.getGroup();
        log.info("WolfKillListener.startWolfKill.signUp=====>sender:{}", qq);
        if (!signUp(qq, event)) {
            return EventResult.truncate();
        }
        //挨个禁言
        group.getMembers().asStream().forEach(item -> item.muteAsync(identityList.size(), TimeUnit.DAYS));
        Collections.shuffle(identityList);
        int count = 0;
        List<Identity> wolfList = new ArrayList<>();
        Map<String, String> numberMap = new HashMap<>();
        String qqAndNameList = "";
        for (String key : map.keySet()) {
            GroupMember member = group.getMember(SimbotUtil.getID(key));
            String identityName = identityList.get(count++);
            Identity identity = new Identity();
            identity.setQq(key);
            identity.setUserName(member.getUsername());
            qqAndNameList += count + " " + member.getUsername() + "(" + key + ")" + "\n";
            if (identityName.equals(IdentityEnum.VILLAGER.getValue())) {
                identity.setIdentityCode(IdentityEnum.VILLAGER.getCode());
                identity.setIdentityName(IdentityEnum.VILLAGER.getValue());
                map.put(key, identity);
            }
            if (identityName.equals(IdentityEnum.WOLF.getValue())) {
                identity.setIdentityCode(IdentityEnum.WOLF.getCode());
                identity.setIdentityName(IdentityEnum.WOLF.getValue());
                wolfList.add(identity);
                map.put(key, identity);
            }
            if (identityName.equals(IdentityEnum.PROPHET.getValue())) {
                identity.setIdentityCode(IdentityEnum.PROPHET.getCode());
                identity.setIdentityName(IdentityEnum.PROPHET.getValue());
                map.put(key, identity);
            }
            if (identityName.equals(IdentityEnum.WITCH.getValue())) {
                identity.setIdentityCode(IdentityEnum.WITCH.getCode());
                identity.setIdentityName(IdentityEnum.WITCH.getValue());
                identity.setAntidote(true);
                identity.setPoison(true);
                map.put(key, identity);
            }
            if (identityName.equals(IdentityEnum.HUNTER.getValue())) {
                identity.setIdentityCode(IdentityEnum.HUNTER.getCode());
                identity.setIdentityName(IdentityEnum.HUNTER.getValue());
                map.put(key, identity);
            }
            log.info("私聊qq:{}，私聊内容:{}", key, identityName);
            numberMap.put(String.valueOf(count), key + ":" + member.getUsername());
            member.sendAsync("你是身份是：" + identityName);
        }
        group.sendBlocking("游戏即将开始，请查看自己的身份牌(已私聊发送)");
        for (int i = 5; i >= 1; i--) {
            group.sendBlocking(String.valueOf(i));
            Thread.sleep(1000);
        }
        group.sendBlocking("天黑请闭眼......");
        group.sendBlocking("嗷呜~~~");
        RedisUtil.set(Constant.WOLF_KILL_NUMBER_KEY + group.getId(), JsonUtil.toJson(numberMap));
        RedisUtil.set(Constant.WOLF_KILL_STATUS_KEY, WolfKillStatusEnum.BLACK_KILL.getCode() + ":" + group.getId());
        blockingSchedule(Constant.WOLF_QUEUE, WolfKillStatusEnum.BLACK_KILL.getCode(), Constant.WOLF_TIME);
        for (Identity entity : wolfList) {
            String key = entity.getQq();
            Identity identity = map.get(key);
            String wolfListStr = wolfList.stream().filter(item -> !key.equals(item.getQq())).map(Identity::getQq).collect(Collectors.joining(","));
            identity.setTeammates(wolfListStr);
            map.put(key, identity);
            GroupMember member = group.getMember(SimbotUtil.getID(key));
            member.sendBlocking("你的狼队友：" + wolfListStr);
            member.sendBlocking("请选择要刀的玩家：\n" + qqAndNameList + "\n注：狼人有" + Constant.WOLF_TIME + "秒的操作时长，期间发送给机器人的消息(只包括文字消息)会同步给其他两个队友。\n投票刀人格式：vote/编号 如“vote/3”刀的就是3号\n一旦选择了就不可更换，请仔细讨论后做出选择。");
        }
        RedisUtil.set(Constant.WOLF_KILL_IDENTITY_KEY + group.getId(), JsonUtil.toJson(map));
        return EventResult.truncate();
    }

    /**
     * 投票
     *
     * @param event
     * @param no
     * @return
     */
    @Listener
    @Filter("vote/{{no}}")
    public EventResult wolfVote(FriendMessageEvent event, @FilterValue("no") String no) throws BusinessException {
        if (StringUtils.isBlank(no)) {
            return EventResult.truncate();
        }
        log.info("WolfKillListener.vote=====>sender:{},no:{}", event.getFriend().getId(), no);
        String statusInfo = RedisUtil.getByKey(Constant.WOLF_KILL_STATUS_KEY);
        String[] split = statusInfo.split(":");
        Integer status = Integer.valueOf(split[0]);
        String qq = event.getFriend().getId().toString();
        String groupNo = split[1];
        Map<String, Identity> identityMap = JSONObject.parseObject(RedisUtil.getByKey(Constant.WOLF_KILL_IDENTITY_KEY + groupNo), Map.class);
        Map<String, String> numberMap = JSONObject.parseObject(RedisUtil.getByKey(Constant.WOLF_KILL_NUMBER_KEY + groupNo), Map.class);
        if (!identityMap.containsKey(qq)) {
            event.replyAsync("您已被淘汰");
            return EventResult.truncate();
        }
        if (!numberMap.containsKey(no)) {
            event.replyAsync("请输入正确的编号");
            return EventResult.truncate();
        }
        Identity identity = JsonUtil.jsonToEntity(JsonUtil.toJson(identityMap.get(qq)), Identity.class);
        if (status.equals(WolfKillStatusEnum.BLACK_KILL.getCode()) && identity.getIdentityCode().equals(IdentityEnum.WOLF.getCode())) {
            boolean flag = wolfVote(groupNo, no, qq, event.getFriend().getUsername());
            if (flag) {
                event.replyBlocking("选择成功，在天亮后会综合其他俩个队友的刀人投票淘汰玩家。");
            }
        }
        if (status.equals(WolfKillStatusEnum.BLACK_PROPHET.getCode()) && identity.getIdentityCode().equals(IdentityEnum.PROPHET.getCode())) {
            Identity identityInfo = JsonUtil.jsonToEntity(JsonUtil.toJson(identityMap.get(numberMap.get(no).split(":")[0])), Identity.class);
            RLock lock = redissonUtil.getLock(Constant.PROPHET_LOCK);
            try {
                lock.lock();
                Integer oldCount = Integer.valueOf(RedisUtil.getByKey(Constant.PROPHET_OLD_VALUE_KEY + groupNo));
                Integer newCount = Integer.valueOf(RedisUtil.judgeKeyIsExists(Constant.PROPHET_NEW_VALUE_KEY + groupNo) ? RedisUtil.getByKey(Constant.PROPHET_NEW_VALUE_KEY + groupNo) : "0");
                String str = no + " " + identityInfo.getUserName() + "(" + identityInfo.getQq() + ")";
                String identityStr = (identityInfo.getIdentityCode().equals(IdentityEnum.WOLF.getCode()) ? IdentityEnum.WOLF.getValue() : "好人");
                if (newCount >= oldCount) {
                    return EventResult.truncate();
                }
                event.replyAsync(str + "的身份是：" + identityStr);
                String teammates = identity.getTeammates();
                identity.setInspected(Objects.isNull(teammates) ? str + identityStr + "\n" : teammates + str + identityStr + "\n");
                identityMap.put(qq, identity);
                RedisUtil.set(Constant.WOLF_KILL_IDENTITY_KEY + groupNo, JsonUtil.toJson(identityMap));
                RedisUtil.set(Constant.PROPHET_NEW_VALUE_KEY + groupNo, String.valueOf(newCount + 1));
            } finally {
                lock.unlock();
            }
        }
        if (identity.getIdentityCode().equals(IdentityEnum.HUNTER.getCode())) {
            RedisUtil.set(Constant.HUNTER_VOTE_KEY + groupNo, no);
        }
        return EventResult.of();
    }

    @Listener
    @Filter("pass")
    public EventResult pass(GroupMessageEvent event) {
        pass();
        return EventResult.of();
    }


    private synchronized void pass() {
        notifyAll();
    }

    @Listener
    public EventResult wolfMessage(FriendMessageEvent event) throws BusinessException {
        String statusInfo = RedisUtil.getByKey(Constant.WOLF_KILL_STATUS_KEY);
        String[] split = statusInfo.split(":");
        Integer status = Integer.valueOf(split[0]);
        String qq = event.getFriend().getId().toString();
        String groupNo = split[1];
        Map<String, JSONObject> identityMap = JSONObject.parseObject(RedisUtil.getByKey(Constant.WOLF_KILL_IDENTITY_KEY + groupNo), Map.class);
        if (!status.equals(WolfKillStatusEnum.BLACK_KILL.getCode())) {
            return EventResult.of();
        }
        log.info("WolfKillListener.wolfMessage=====>sender:{},content:{}", event.getFriend().getId(), event.getMessageContent().getPlainText());
        if (!identityMap.containsKey(qq)) {
            event.replyAsync("您已被淘汰");
            return EventResult.truncate();
        }
        Identity me = JsonUtil.jsonToEntity(JsonUtil.toJson(identityMap.get(qq)), Identity.class);
        String teammates = me.getTeammates();
        BotManagers botManagers = application.getBotManagers();
        Bot bot = botManagers.get(0).all().get(0);
        for (String str : teammates.split(",")) {
            GroupMember member = bot.getGroup(SimbotUtil.getID(groupNo)).getMember(SimbotUtil.getID(str));
            member.sendBlocking(me.getUserName() + "(" + qq + ")说：" + event.getMessageContent().getPlainText());
        }
        return EventResult.of();
    }

    @Listener
    @Filter("预言记录")
    public EventResult checkRecords(FriendMessageEvent event) throws BusinessException {
        log.info("WolfKillListener.checkRecords=====>sender:{}", event.getFriend().getId());
        String statusInfo = RedisUtil.getByKey(Constant.WOLF_KILL_STATUS_KEY);
        String[] split = statusInfo.split(":");
        String qq = event.getFriend().getId().toString();
        String groupNo = split[1];
        Map<String, JSONObject> identityMap = JSONObject.parseObject(RedisUtil.getByKey(Constant.WOLF_KILL_IDENTITY_KEY + groupNo), Map.class);
        if (!identityMap.containsKey(qq)) {
            event.replyAsync("您已被淘汰");
            return EventResult.truncate();
        }
        Identity identity = JsonUtil.jsonToEntity(JsonUtil.toJson(identityMap.get(qq)), Identity.class);
        if (identity.getIdentityCode().equals(IdentityEnum.PROPHET.getCode())) {
            event.getFriend().sendBlocking(identity.getInspected());
        }
        return EventResult.of();
    }

    @Listener
    @Filter("使用解药")
    public EventResult antidote(FriendMessageEvent event) throws BusinessException {
        log.info("WolfKillListener.antidote=====>sender:{}", event.getFriend().getId());
        String statusInfo = RedisUtil.getByKey(Constant.WOLF_KILL_STATUS_KEY);
        String[] split = statusInfo.split(":");
        Integer status = Integer.valueOf(split[0]);
        String qq = event.getFriend().getId().toString();
        String groupNo = split[1];
        Map<String, Identity> identityMap = JSONObject.parseObject(RedisUtil.getByKey(Constant.WOLF_KILL_IDENTITY_KEY + groupNo), Map.class);
        if (!identityMap.containsKey(qq)) {
            event.replyAsync("您已被淘汰");
            return EventResult.truncate();
        }
        Identity identity = JsonUtil.jsonToEntity(JsonUtil.toJson(identityMap.get(qq)), Identity.class);
        if (status.equals(WolfKillStatusEnum.BLACK_WITCH.getCode()) && identity.getIdentityCode().equals(IdentityEnum.WITCH.getCode())) {
            RLock lock = redissonUtil.getLock(Constant.WITCH_LOCK);
            try {
                lock.lock();
                Map<String, Identity> newMap = JSONObject.parseObject(RedisUtil.getByKey(Constant.WOLF_KILL_IDENTITY_KEY + groupNo), Map.class);
                Identity newIdentity = JsonUtil.jsonToEntity(JsonUtil.toJson(newMap.get(qq)), Identity.class);
                if (newIdentity.isAntidote()) {
                    identity.setAntidote(false);
                    identityMap.put(qq, identity);
                    RedisUtil.set(Constant.WOLF_KILL_IDENTITY_KEY + groupNo, JsonUtil.toJson(identityMap));
                    RedisUtil.deleteByKey(Constant.WOLF_VOTE_KEY + groupNo);
                    event.replyBlocking("解药使用成功");
                }
            } finally {
                lock.unlock();
            }
        }
        return EventResult.of();
    }

    @Listener
    @Filter("d/{{no}}")
    public EventResult poison(FriendMessageEvent event, @FilterValue("no") String no) throws BusinessException {
        if (StringUtils.isBlank(no)) {
            return EventResult.of();
        }
        log.info("WolfKillListener.poison=====>sender:{}", event.getFriend().getId());
        String statusInfo = RedisUtil.getByKey(Constant.WOLF_KILL_STATUS_KEY);
        String[] split = statusInfo.split(":");
        Integer status = Integer.valueOf(split[0]);
        String qq = event.getFriend().getId().toString();
        String groupNo = split[1];
        Map<String, Identity> identityMap = JSONObject.parseObject(RedisUtil.getByKey(Constant.WOLF_KILL_IDENTITY_KEY + groupNo), Map.class);
        if (!identityMap.containsKey(qq)) {
            event.replyAsync("您已被淘汰");
            return EventResult.truncate();
        }
        Identity identity = JsonUtil.jsonToEntity(JsonUtil.toJson(identityMap.get(qq)), Identity.class);
        if (status.equals(WolfKillStatusEnum.BLACK_WITCH.getCode()) && identity.getIdentityCode().equals(IdentityEnum.WITCH.getCode())) {
            RLock lock = redissonUtil.getLock(Constant.WITCH_LOCK);
            try {
                lock.lock();
                Map<String, Identity> newMap = JSONObject.parseObject(RedisUtil.getByKey(Constant.WOLF_KILL_IDENTITY_KEY + groupNo), Map.class);
                Identity newIdentity = JsonUtil.jsonToEntity(JsonUtil.toJson(newMap.get(qq)), Identity.class);
                if (newIdentity.isPoison()) {
                    identity.setPoison(false);
                    identityMap.put(qq, identity);
                    RedisUtil.set(Constant.WOLF_KILL_IDENTITY_KEY + groupNo, JsonUtil.toJson(identityMap));
                    Vote vote = new Vote();
                    vote.setNumber(no);
                    vote.setCount(1);
                    RedisUtil.set(Constant.WITCH_VOTE_KEY + groupNo, JsonUtil.toJson(vote));
                    event.replyBlocking("毒药使用成功");
                }
            } finally {
                lock.unlock();
            }
        }
        return EventResult.of();
    }

    private synchronized boolean wolfVote(String groupNo, String no, String qq, String username) throws BusinessException {
        boolean flag = RedisUtil.judgeKeyIsExists(Constant.WOLF_VOTE_KEY + groupNo);
        if (!flag) {
            List<Vote> newList = new ArrayList<>();
            Vote vote = new Vote();
            vote.setNumber(no);
            vote.setCount(1);
            vote.setQqs(username + "(" + qq + ") ");
            newList.add(vote);
            RedisUtil.set(Constant.WOLF_VOTE_KEY + groupNo, JsonUtil.toJson(newList));
            return true;
        }
        List<Vote> oldList = JsonUtil.jsonToList(RedisUtil.getByKey(Constant.WOLF_VOTE_KEY + groupNo), Vote.class);
        for (Vote vote : oldList) {
            if (vote.getQqs().contains(qq)) {
                return false;
            }
            if (vote.getNumber().equals(no)) {
                vote.setCount(vote.getCount() + 1);
                vote.setQqs(vote.getQqs() + username + "(" + qq + ") ");
            }
        }
        RedisUtil.set(Constant.WOLF_VOTE_KEY + groupNo, JsonUtil.toJson(oldList));
        return true;
    }


    @Listener
    @GroupAnnotation(value = true)
    @Filter("初始化")
    public EventResult init(GroupMessageEvent event) {
        map.put("702272198", null);
        map.put("3503651428", null);
        map.put("1154220981", null);
        map.put("2661723102", null);
        map.put("2422248615", null);
        map.put("3092515903", null);
        map.put("1715182483", null);
        map.put("2632238487", null);
        map.put("329249172", null);
        map.put("2644502646", null);
        Collections.shuffle(identityList);
        wolfKillStatus = false;
        return EventResult.of();
    }

    @Listener
    @Filter("私我")
    public EventResult test(GroupMessageEvent event) {
        event.getGroup().getMember(event.getAuthor().getId()).sendBlocking("你好");
        return EventResult.of();
    }

    @Listener
    @Filter("test")
    public EventResult test1(GroupMessageEvent event) throws BusinessException {
        String byKey = RedisUtil.getByKey(Constant.WOLF_KILL_IDENTITY_KEY + "891425814");
        System.out.println(byKey);
        return EventResult.of();
    }

    private synchronized boolean signUp(String qq, GroupMessageEvent event) {
        map.put(qq, null);
        if (map.size() == identityList.size()) {
//            wolfKillStatus = false;
            return true;
        }
        event.getGroup().sendBlocking("当前报名人数：" + identityList.size() + "/" + map.size());
        return false;
    }

    private synchronized boolean startWolfKill() {
        if (wolfKillStatus) {
            return false;
        }
        return wolfKillStatus = true;
    }

    private void blockingSchedule(String queueName, Integer status, Long expireTime) {
        //目标阻塞队列
        RBlockingQueue<String> blockingRedPacketQueue = redissonUtil.getBlockingQueue(queueName);
        //目标延时队列
        RDelayedQueue<String> delayedRedPacketQueue = redissonUtil.getDelayedQueue(blockingRedPacketQueue);
        //将当前游戏状态存入
        delayedRedPacketQueue.offer(String.valueOf(status), expireTime, TimeUnit.SECONDS);
    }

}
